/*
 * 机器模式启动代码
 * 设置中断委托，初始化时钟，然后切换到supervisor模式
 */

#include "riscv_regs.h"
#include "trap.h"
#include "../fs/printf.h"

// 外部函数声明
extern void main(void);
extern void timervec(void);

// 前向声明
void timerinit(void);

/*
 * 机器模式启动函数
 * 在entry.S中被调用
 */
void start(void)
{
    // 设置M Previous Privilege mode为Supervisor，用于mret
    uint64 x = r_mstatus();
    x &= ~MSTATUS_MPP_MASK;
    x |= MSTATUS_MPP_S;
    w_mstatus(x);

    // 设置M Exception Program Counter为main，用于mret
    w_mepc((uint64)main);

    // 禁用分页
    asm volatile("csrw satp, zero");

    // 将所有中断和异常委托给supervisor模式
    w_medeleg(0xffff);
    w_mideleg(0xffff);

    // 配置物理内存保护，给supervisor模式访问所有物理内存的权限
    // PMP地址寄存器0设置为最大地址
    asm volatile("csrw pmpaddr0, %0" : : "r" (0x3fffffffffffffull));
    // PMP配置寄存器0设置为读写执行权限
    asm volatile("csrw pmpcfg0, %0" : : "r" (0xf));

    // 保存hart id到tp寄存器
    int id = r_mhartid();
    asm volatile("mv tp, %0" : : "r" (id));

    // 切换到supervisor模式并跳转到main()
    asm volatile("mret");
}

/*
 * 请求每个hart生成时钟中断
 */
void timerinit(void)
{
    // 简化的时钟初始化
    // 在supervisor模式下初始化时钟
}